/**
 *  @file XmlTokenizer.h
 */
#ifndef _XMLTOKENIZER_H_
#define _XMLTOKENIZER_H_

#include "../../../common/BaseObject.h"
#include "../../../text/CFString.h"
#include "../../../io/Stream.h"


namespace cppflib
{

namespace collections
{
   class BinBuf;  // forward declaration
}

namespace xml
{

namespace sax
{

class XmlTokenizer : public BaseObject
{
public:
    //! specific error while fetching token
    typedef enum 
    {
       FERR_NONE,
       FERR_CDATA_END_DISALLOW,
    } fetchingerror_t;

    //! token type
    typedef enum
    {
       XML_UNKNOWN,
       XML_ERROR_GENERAL,
       XML_ERROR_XML_DECL_START, // <?xml not started at the first character

       XML_STREAMEND,

       XML_DECL_START,   // '<?xml'
       XML_DECL_END,     // '?>'
       XML_STYLESHEET_START,   // '<?xml-stylesheet'
       XML_DOCTYPE_START, // <!DOCTYPE
       XML_KEYWORD_SYSTEM, // SYSTEM
       XML_KEYWORD_PUBLIC, // PUBLIC
       XML_KEYWORD_OPENSQUAREBRACKET, // [
       XML_COMMENT_START, // <!-- 
       XML_COMMENT_END, // --> 
       XML_CDATA_START, // <![CDATA[
       XML_ATTRNAME,
       XML_EQU,         // '='
       XML_ATTRVALUE,
       XML_TAGSTART,         // '<xxxx'
       XML_TAGCLOSE_1,       // '/>'
       XML_TAGCLOSE_2,       // '>'
       XML_TAGCLOSE_3,       // ']>'
       XML_CLOSINGTAGSTART,  // '</xxxx'

       XML_OPENINGTAG_CLOSE, // '>', same as TAGCLOSE_2 but for opening tag
       XML_CLOSINGTAG_CLOSE, // '>', same as TAGCLOSE_2 but for closing tag

    } tokentype_t;
private:
    int lineNum;  ///< line number
    io::Stream *pStream; ///< input stream
    collections::BinBuf *pTempBuf;  ///< temp buffer
    int docTypeCount;      ///< number of DOCTYPE declared
    int styleSheetCount;   ///< number of style sheet declared
    fetchingerror_t fetchingError;

private:
    XmlTokenizer(void);

public:
    explicit XmlTokenizer(io::Stream *pStream);
    virtual ~XmlTokenizer(void);

    void IncrementLineNumber();
    io::Stream *GetStream();
    collections::BinBuf *GetTempBuffer();    
    int GetLineNumber();
    int GetDocTypeCount();
    int GetStyleSheetCount();
    fetchingerror_t GetFetchingError();

    tokentype_t GetToken(CFString &token);
    bool CollectElementContent(CFString &content);
    bool CollectCDATAContent(CFString &content);
};

} // end of namespace sax

} // end of namespace xml

} // end of namespace cppflib

#endif
